package com.ys.erp.stage_mall_service.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ys.erp.common.enums.EnableEnum;
import com.ys.erp.common.enums.RedisKey;
import com.ys.erp.common.util.DateUtil;
import com.ys.erp.common.util.MoneyUtil;
import com.ys.erp.common.util.YsThread;
import com.ys.erp.entity.data.bean.MallHomeActivity;
import com.ys.erp.entity.data.bean.MallHomeActivityCoupons;
import com.ys.erp.entity.data.bean.MallHomeGoods;
import com.ys.erp.entity.service.IMallHomeActivityCouponsService;
import com.ys.erp.entity.service.IMallHomeActivityService;
import com.ys.erp.entity.service.IMallHomeGoodsService;
import com.ys.erp.framework.bean.dto.StageEmpDTO;
import com.ys.erp.framework.exception.YsException;
import com.ys.erp.stage_mall_service.bean.condition.HomeActivityCondition;
import com.ys.erp.stage_mall_service.bean.vo.HomeActivityInfoVO;
import com.ys.erp.stage_mall_service.bean.vo.HomeActivityVO;
import com.ys.erp.stage_mall_service.task.ActivityTask;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author minamiyama
 * @date 2025/5/27 15:49
 */
@Service
@RequiredArgsConstructor
public class HomeMallActivityService {
    private final IMallHomeActivityService iMallHomeActivityService;
    private final IMallHomeActivityCouponsService iMallHomeActivityCouponsService;
    private final RedisTemplate<String, Object> redisTemplate;
    private final IMallHomeGoodsService iMallHomeGoodsService;
    private final ActivityTask activityTask;

    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdateHomeActivity(HomeActivityCondition.AddOrUpdateCon con, StageEmpDTO emp) {
        if (Objects.isNull(con.getId())) {
            MallHomeActivity activity = new MallHomeActivity();
            activity.setActivityType(con.getActivityType());
            activity.setActivityName(con.getActivityName());
            activity.setStartTime(DateUtil.stringToLocalDateTime(con.getStartTime()));
            activity.setEndTime(DateUtil.stringToLocalDateTime(con.getEndTime()));
            activity.setLocation(con.getLocation());
            activity.setStatus(con.getStatus());
            activity.setEmpId(emp.getId());
            activity.setEmpPhone(emp.getPhone());
            activity.setEmpName(emp.getRealName());
            activity.setActivityStatus(activity.getActivityStatus(con.getStartTime(), con.getEndTime()));
            activity.setNo("activity" + UUID.randomUUID());
            iMallHomeActivityService.save(activity);
            if (CollectionUtils.isNotEmpty(con.getActivityCouponsConList())) {
                ArrayList<MallHomeActivityCoupons> coupons = new ArrayList<>();
                boolean hasDuplicate = con.getActivityCouponsConList().stream()
                        .map(HomeActivityCondition.ActivityCouponsCon::getCouponsId)
                        .collect(Collectors.groupingBy(id -> id, Collectors.counting()))
                        .values()
                        .stream()
                        .anyMatch(count -> count > 1);
                if (hasDuplicate) {
                    throw new RuntimeException("优惠券不能重复");
                }
                saveMallHomeActivityCoupons(con, activity, coupons);
            }
            if (con.getGoodsInfoList().isEmpty()) {
                return;
            }
            ArrayList<MallHomeGoods> mallHomeGoods = new ArrayList<>();
            for (HomeActivityCondition.GoodsInfo goodsInfo : con.getGoodsInfoList()) {
                MallHomeGoods goods = new MallHomeGoods();
                goods.setGoodsSendMethod(goodsInfo.getSendGoodsMethod());
                BeanUtils.copyProperties(goodsInfo, goods);
                goods.setHomeGroupNo(activity.getNo());
                goods.setPrice(MoneyUtil.str2Long(goodsInfo.getPrice()));
                mallHomeGoods.add(goods);
            }
            iMallHomeGoodsService.saveBatch(mallHomeGoods);

            return;
        }
        if (Objects.requireNonNull(DateUtil.stringToLocalDate(con.getEndTime())).isAfter(LocalDate.now())) {
            activityTask.activityStatusTask();
        }
        MallHomeActivity activity = iMallHomeActivityService.getById(con.getId());
        activity.setActivityType(con.getActivityType());
        activity.setActivityName(con.getActivityName());
        activity.setStartTime(DateUtil.stringToLocalDateTime(con.getStartTime()));
        activity.setEndTime(DateUtil.stringToLocalDateTime(con.getEndTime()));
        activity.setLocation(con.getLocation());
        activity.setStatus(con.getStatus());
        activity.setActivityStatus(activity.getActivityStatus(con.getStartTime(), con.getEndTime()));
        iMallHomeActivityService.updateById(activity);
        QueryWrapper<MallHomeActivityCoupons> couponsQw = new QueryWrapper<>();
        couponsQw.lambda().eq(MallHomeActivityCoupons::getActivityId, activity.getId());
        iMallHomeActivityCouponsService.remove(couponsQw);
        LambdaQueryWrapper<MallHomeGoods> oldGoodsQw = new LambdaQueryWrapper<>();
        oldGoodsQw.eq(MallHomeGoods::getHomeGroupNo, activity.getNo());
        iMallHomeGoodsService.remove(oldGoodsQw);
        if (CollectionUtils.isNotEmpty(con.getActivityCouponsConList())) {
            redisTemplate.delete(RedisKey.Enums.ACTIVITY_COUPONS.getKey() + activity.getNo() + "*");
            boolean hasDuplicate = con.getActivityCouponsConList().stream()
                    .map(HomeActivityCondition.ActivityCouponsCon::getCouponsId)
                    .collect(Collectors.groupingBy(id -> id, Collectors.counting()))
                    .values()
                    .stream()
                    .anyMatch(count -> count > 1);
            if (hasDuplicate) {
                throw new RuntimeException("优惠券不能重复");
            }
            ArrayList<MallHomeActivityCoupons> coupons = new ArrayList<>();
            saveMallHomeActivityCoupons(con, activity, coupons);

        }
        if (con.getGoodsInfoList().isEmpty()) {
            return;
        }
        ArrayList<MallHomeGoods> mallHomeGoods = new ArrayList<>();
        for (HomeActivityCondition.GoodsInfo goodsInfo : con.getGoodsInfoList()) {
            MallHomeGoods goods = new MallHomeGoods();
            goods.setGoodsSendMethod(goodsInfo.getSendGoodsMethod());
            BeanUtils.copyProperties(goodsInfo, goods);
            goods.setHomeGroupNo(activity.getNo());
            goods.setPrice(MoneyUtil.str2Long(goodsInfo.getPrice()));
            mallHomeGoods.add(goods);
        }
        iMallHomeGoodsService.saveBatch(mallHomeGoods);

    }

    private void saveMallHomeActivityCoupons(HomeActivityCondition.AddOrUpdateCon con, MallHomeActivity activity, ArrayList<MallHomeActivityCoupons> coupons) {
        for (HomeActivityCondition.ActivityCouponsCon couponsCon : con.getActivityCouponsConList()) {
            MallHomeActivityCoupons coupon = new MallHomeActivityCoupons();
            coupon.setActivityId(activity.getId());
            coupon.setActivityNo(activity.getNo());
            BeanUtils.copyProperties(couponsCon, coupon);
            coupon.setAdoptRule(JSONObject.toJSONString(couponsCon.getAdoptRule()));
            coupon.setTimingRule(JSONObject.toJSONString(couponsCon.getTimIngRule()));
            coupons.add(coupon);
            //添加优惠券库存存入redis
            if (activity.getActivityStatus().equals(MallHomeActivity.Enums.ONGOING.toString())) {
                redisTemplate.opsForValue().set(RedisKey.Enums.ACTIVITY_COUPONS.getKey() + activity.getNo() + ":" + couponsCon.getCouponsId(),
                        couponsCon.getSendNum(), DateUtil.getMinutesUntil(con.getEndTime()), TimeUnit.MINUTES);
            }

        }
        iMallHomeActivityCouponsService.saveBatch(coupons);

    }

    @Transactional(rollbackFor = Exception.class)
    public void delHomeActivity(Long homeActivityId, StageEmpDTO emp) {
        MallHomeActivity activity = iMallHomeActivityService.getById(homeActivityId);
        if (Objects.isNull(activity)) {
            throw new YsException(-1, "源数据不存在，无法删除");
        }
 /*       if (DateUtil.isBetween(activity.getStartTime(), activity.getEndTime(), LocalDateTime.now())) {
            throw new YsException(-1, "活动正在进行中，无法删除");
        }*/
        activity.setIsDelete(EnableEnum.YES.getEnable());
        activity.setEmpId(emp.getId());
        activity.setEmpPhone(emp.getPhone());
        activity.setEmpName(emp.getRealName());
        iMallHomeActivityService.updateById(activity);
        redisTemplate.delete(RedisKey.Enums.ACTIVITY_COUPONS.getKey() + activity.getNo() + "*");
    }


    public void updateHomeActivityStatus(Long homeActivityId, StageEmpDTO emp) {
        MallHomeActivity activity = iMallHomeActivityService.getById(homeActivityId);
        if (Objects.isNull(activity)) {
            throw new YsException(-1, "源数据不存在，无法修改");
        }
        activity.setStatus(activity.getStatus() == 1 ? 0 : 1);
        activity.setEmpName(emp.getRealName());
        activity.setEmpPhone(emp.getPhone());
        activity.setEmpId(emp.getId());
        iMallHomeActivityService.updateById(activity);
    }

    /**
     * 获取活动列表
     *
     * @param emp 员工信息
     * @return 活动列表
     */
    public List<HomeActivityVO> getHomeActivityList(StageEmpDTO emp) {
        QueryWrapper<MallHomeActivity> activityQw = new QueryWrapper<>();
        activityQw.lambda().eq(MallHomeActivity::getIsDelete, EnableEnum.NO.getEnable());
        List<MallHomeActivity> activities = iMallHomeActivityService.list(activityQw);
        CompletableFuture<Map<String, Long>> activitiesGoodsNumMapFuture = YsThread.execute(() -> {
            List<String> activitiesNoList = activities.stream().map(MallHomeActivity::getNo).toList();
            if (activitiesNoList.isEmpty()) {
                return Collections.emptyMap();
            }
            QueryWrapper<MallHomeGoods> goodsQw = new QueryWrapper<>();
            goodsQw.lambda().in(MallHomeGoods::getHomeGroupNo, activitiesNoList);
            List<MallHomeGoods> goodsList = iMallHomeGoodsService.list(goodsQw);
            return goodsList.stream().collect(Collectors.groupingBy(MallHomeGoods::getHomeGroupNo, Collectors.counting()));
        });
        Map<String, Long> activitiesGoodsNumMap = activitiesGoodsNumMapFuture.join();
        ArrayList<HomeActivityVO> results = new ArrayList<>();
        for (MallHomeActivity activity : activities) {
            HomeActivityVO vo = new HomeActivityVO();
            BeanUtils.copyProperties(activity, vo);
            vo.setGoodsNum(activitiesGoodsNumMap.getOrDefault(activity.getNo(), 0L).intValue());
            vo.setActivityTime(DateUtil.localDateTimeFormatTwo(activity.getStartTime()) + "~" + DateUtil.localDateTimeFormatTwo(activity.getEndTime()));
            vo.setEmp(activity.getEmpName() + "(" + activity.getEmpPhone() + ")");
            vo.setActivityStatus(MallHomeActivity.ENUM_MAP.get(activity.getActivityStatus()));
            vo.setUpdateTime(DateUtil.localDateTimeFormatTwo(activity.getUpdateTime()));
            results.add(vo);
        }
        return results;
    }

    public HomeActivityInfoVO getHomeActivityInfo(Long homeActivityId) {
        QueryWrapper<MallHomeActivity> activityQw = new QueryWrapper<>();
        activityQw.lambda().eq(MallHomeActivity::getId, homeActivityId);
        activityQw.lambda().eq(MallHomeActivity::getIsDelete, EnableEnum.NO.getEnable());
        MallHomeActivity activity = iMallHomeActivityService.getOne(activityQw);
        if (Objects.isNull(activity)) {
            throw new YsException(-1, "源数据不存在");
        }
        HomeActivityInfoVO vo = new HomeActivityInfoVO();
        BeanUtils.copyProperties(activity, vo);
        QueryWrapper<MallHomeActivityCoupons> couponsQw = new QueryWrapper<>();
        couponsQw.lambda().eq(MallHomeActivityCoupons::getActivityNo, activity.getNo());
        List<MallHomeActivityCoupons> couponsList = iMallHomeActivityCouponsService.list(couponsQw);
        if (couponsList.isEmpty()) {
            vo.setActivityCouponsInfoVOList(new ArrayList<>());
        } else {
            ArrayList<HomeActivityInfoVO.ActivityCouponsInfoVO> couponsInfoVos = new ArrayList<>();
            for (MallHomeActivityCoupons coupons : couponsList) {
                HomeActivityInfoVO.ActivityCouponsInfoVO couponVo = new HomeActivityInfoVO.ActivityCouponsInfoVO();
                couponVo.setCouponsId(coupons.getCouponsId());
                couponVo.setSendMethod(coupons.getSendMethod());
                couponVo.setSendNum(coupons.getSendNum());
                couponVo.setAdoptRule(JSONObject.parseObject(coupons.getAdoptRule(), MallHomeActivityCoupons.AdoptRuleDTO.class));
                couponVo.setIsTiming(coupons.getIsTiming());
                couponVo.setTimIngRule(JSONObject.parseObject(coupons.getTimingRule(), MallHomeActivityCoupons.TimingRuleDTO.class));
                couponVo.setIsAuto(coupons.getIsAuto());
                couponsInfoVos.add(couponVo);
            }
            vo.setActivityCouponsInfoVOList(couponsInfoVos);
        }

        QueryWrapper<MallHomeGoods> goodsQw = new QueryWrapper<>();
        goodsQw.lambda().eq(MallHomeGoods::getHomeGroupNo, activity.getNo());
        List<MallHomeGoods> goodsList = iMallHomeGoodsService.list(goodsQw);
        if (goodsList.isEmpty()) {
            vo.setGoodsNum(new ArrayList<>());
            return vo;
        }
        ArrayList<HomeActivityInfoVO.GoodsInfoVO> goodsInfoVoList = new ArrayList<>();
        for (MallHomeGoods goods : goodsList) {
            HomeActivityInfoVO.GoodsInfoVO goodsInfoVO = new HomeActivityInfoVO.GoodsInfoVO();
            BeanUtils.copyProperties(goods, goodsInfoVO);
            goodsInfoVO.setPrice(MoneyUtil.long2Str(goods.getPrice()));
            goodsInfoVO.setSendGoodsMethod(goods.getGoodsSendMethod());
            goodsInfoVoList.add(goodsInfoVO);
        }
        vo.setGoodsNum(goodsInfoVoList);
        return vo;
    }


}
